/*
 * Copyright (c) 2012 swing-on-fire Team
 * 
 * This file is part of Swing-On-Fire (http://code.google.com/p/swing-on-fire), licensed under the terms of the MIT
 * License (MIT).
 * 
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
 * documentation files (the "Software"), to deal in the Software without restriction, including without limitation the
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to the following conditions:
 * 
 * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the
 * Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
 * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
package com.google.code.swingonfire.component.page.old;

import java.awt.Component;
import java.util.HashMap;
import java.util.Map;

public class JPagePane extends AbstractJPageComponent
{

    private static final long serialVersionUID = -4125616654057637490L;

    private final Map<String, Component> pages = new HashMap<String, Component>();

    private boolean loopPages;
    private JPageAnimationFactory animationFactory;
    private JPageAnimationFactory animationFactoryForPrevious;
    private JPageAnimationFactory animationFactoryForNext;
    private JPageAnimationFactory animationFactoryForAnyPrevious;
    private JPageAnimationFactory animationFactoryForAnyNext;

    public JPagePane()
    {
        super();
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Component add(Component component)
    {
        return addPage(component.getName(), component);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public Component add(Component component, int index)
    {
        return addPage(component.getName(), index, component);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void add(Component comp, Object constraints)
    {
        addPage((String) constraints, comp);
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void add(Component comp, Object constraints, int index)
    {
        addPage((String) constraints, index, comp);
    }

    public Component addPage(String title, Component component)
    {
        return addPage(title, pages.size(), component);
    }

    public Component addPage(String title, int index, Component component)
    {
        Component existingComponent = pages.get(title);

        if (existingComponent != null)
        {
            remove(existingComponent);
            pages.remove(title);
        }

        component.setVisible(false);

        pages.put(title, component);

        super.add(component, index);

        revalidate();
        repaint();

        if (getActiveComponent() == null)
        {
            show(component);
        }

        return component;
    }

    public int getIndexOfComponent(String title)
    {
        Component component = pages.get(title);

        if (component == null)
        {
            return -1;
        }

        return getIndexOfComponent(component);
    }

    public int getIndexOfComponent(Component component)
    {
        for (int i = 0; i < getComponentCount(); i += 1)
        {
            if (getComponent(i) == component)
            {
                return i;
            }
        }

        return -1;
    }

    public int getSelectedComponentIndex()
    {
        return getIndexOfComponent(getActiveComponent());
    }

    public void setSelectedComponent(String title)
    {
        int index = getIndexOfComponent(title);

        if (index >= 0)
        {
            setSelectedComponent(index);
        }
    }

    public void setSelectedComponent(int index)
    {
        setSelectedComponent(getComponent(index));
    }

    private void setSelectedComponent(Component component)
    {
        show(component);
    }

    public boolean isLoopPages()
    {
        return loopPages;
    }

    public void setLoopPages(boolean loopPages)
    {
        this.loopPages = loopPages;
    }

    public JPageAnimationFactory getAnimationFactory()
    {
        return animationFactory;
    }

    public void setAnimationFactory(JPageAnimationFactory animationFactory)
    {
        this.animationFactory = animationFactory;
    }

    public JPageAnimationFactory getAnimationFactoryForPrevious()
    {
        return (animationFactoryForPrevious != null) ? animationFactoryForPrevious
            : getAnimationFactoryForAnyPrevious();
    }

    public void setAnimationFactoryForPrevious(JPageAnimationFactory animationFactoryForPrevious)
    {
        this.animationFactoryForPrevious = animationFactoryForPrevious;
    }

    public JPageAnimationFactory getAnimationFactoryForNext()
    {
        return (animationFactoryForNext != null) ? animationFactoryForNext : getAnimationFactoryForAnyNext();
    }

    public void setAnimationFactoryForNext(JPageAnimationFactory animationFactoryForNext)
    {
        this.animationFactoryForNext = animationFactoryForNext;
    }

    public JPageAnimationFactory getAnimationFactoryForAnyPrevious()
    {
        return (animationFactoryForAnyPrevious != null) ? animationFactoryForAnyPrevious : getAnimationFactory();
    }

    public void setAnimationFactoryForAnyPrevious(JPageAnimationFactory animationFactoryForAnyPrevious)
    {
        this.animationFactoryForAnyPrevious = animationFactoryForAnyPrevious;
    }

    public JPageAnimationFactory getAnimationFactoryForAnyNext()
    {
        return (animationFactoryForAnyNext != null) ? animationFactoryForAnyNext : getAnimationFactory();
    }

    public void setAnimationFactoryForAnyNext(JPageAnimationFactory animationFactoryForAnyNext)
    {
        this.animationFactoryForAnyNext = animationFactoryForAnyNext;
    }

    private JPageAnimationFactory getAnimationFactory(int activeIndex, int pendingIndex)
    {
        JPageAnimationFactory factory = null;

        if ((activeIndex < 0) || (pendingIndex < 0))
        {
            factory = getAnimationFactory();
        }
        else if ((loopPages) && (activeIndex == (getComponentCount() - 1)) && (pendingIndex == 0))
        {
            factory = getAnimationFactoryForNext();
        }
        else if ((loopPages) && (activeIndex == 0) && (pendingIndex == (getComponentCount() - 1)))
        {
            factory = getAnimationFactoryForPrevious();
        }
        else if (pendingIndex < activeIndex)
        {
            if (pendingIndex == (activeIndex - 1))
            {
                factory = getAnimationFactoryForPrevious();
            }
            else
            {
                factory = getAnimationFactoryForAnyPrevious();
            }
        }
        else
        {
            if (pendingIndex == (activeIndex + 1))
            {
                factory = getAnimationFactoryForNext();
            }
            else
            {
                factory = getAnimationFactoryForAnyNext();
            }
        }

        return factory;
    }

    @Override
    protected void startAnimation()
    {
        if (getAnimation() != null)
        {
            return;
        }

        if (getPendingComponent() == null)
        {
            return;
        }

        startAnimation(getAnimationFactory(getIndexOfComponent(getActiveComponent()),
            getIndexOfComponent(getPendingComponent())));
    }

}
